package com.evendai.loglibrary

import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import android.os.Environment
import android.util.Log
import androidx.core.content.ContextCompat
import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.classic.joran.JoranConfigurator
import org.slf4j.LoggerFactory
import java.io.ByteArrayInputStream
import java.io.File

//配置应该框架初始化之前就设置好，否则只生效默认的设置
object TimberConfig {

    var pushService = true

    //source，不允许带空格
    private var graylogSource = "localhost"

    //日志前缀
    var graylogSuffixPattern = " default "

    //服务器地址
    var graylogHost = "192.168.1.214"

    //服务器端口
    var graylogPort = 1514

    //本地缓存大小上限，单位 MB
    var localSize = 600

    //本地存储时间长度,保存 30 天的历史记录(30天后会删除最老的日志文件)
    var localMaxHistory = 30

    //日志格式
    var logFormat = "%d{yyyy_MM_dd HH:mm:ss:SSS} [%thread] %-5level %msg%n"


    //声明日志来源【来自系统、用户、或者其他等等】
    //The facility option must be set to one of the strings

    // KERN, USER, MAIL, DAEMON, AUTH, SYSLOG, LPR, NEWS, UUCP, CRON, AUTHPRIV, FTP, NTP, AUDIT, ALERT,
    // CLOCK, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7

    // Case is not important.
    var facility = "USER"

    //这两个不需要手动设置
    var rootPath = ""
    var packName = ""
    @Suppress("MemberVisibilityCanBePrivate")
    val logDir: String
        get() {
            val dir = if (Timber.isUseSdcardRootPath) {
                "$rootPath/$packName"
            } else {
                "$rootPath/Android/data/$packName/files/Documents"
            }
            Log.i(Timber::class.java.simpleName, "Timber日志存储目录为：$dir")
            return dir
        }

    val bugFilesDir: File get() = File(logDir, "/bugs")
    val logFilesDir: File get() = File(logDir, "/logs")

    fun hasStoragePermission(): Boolean {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            Environment.isExternalStorageManager()
        } else {
            ContextCompat.checkSelfPermission(Timber.application, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
        }
    }

    //生成配置字符串
    private fun getConfigStr(): String {
        var pushServiceConfig = ""
        var rootPushServiceConfig = ""
        if (pushService) {
            pushServiceConfig = """
                <appender name="PAPERTRAIL" class="com.evendai.loglibrary.MySyslogAppender">
                    <!-- 只有WARN和ERROR的日志才会上传 -->
                    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                        <!-- 过虑掉小于WARN级别的日志，所有级别: TRACE < DEBUG < INFO < WARN < ERROR -->
                        <level>ERROR</level>
                        <level>WARN</level>
                    </filter>
                    <suffixPattern>${graylogSuffixPattern} ${logFormat}</suffixPattern>
                    <syslogHost>${graylogHost}</syslogHost>
                    <port>${graylogPort}</port>
                    <facility>$facility</facility>
                    <lazy>true</lazy>
                </appender>

                <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
                    <appender-ref ref="PAPERTRAIL" />
                </appender>
            """.trimIndent()
            rootPushServiceConfig = """
                <appender-ref ref="ASYNC" />
            """.trimIndent()
        }
        return """
        <configuration>
            
            <!--当Logback运行起来后创建了日志文件，如果此时手动删除，则Logback不会再创建文件出来了，写日志也就写不到了，除非杀进程重启才行-->

            <!--用于保存运行日志的Appender配置-->
            <appender name="FILE_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">

                <!--过滤：不要ERROR级别，其它级别都要-->
                <filter class="ch.qos.logback.classic.filter.LevelFilter">
                    <level>ERROR</level>
                    <onMatch>DENY</onMatch>
                    <onMismatch>ACCEPT</onMismatch>
                </filter>

                <!--PACKAGE_NAME 应用包名-->
                <!--好像写数据到/sdcard/Android/data/应用包名目录下是不需要权限，但是实验证明需要写外部存储权限才可以-->
                <file>${logDir}/logs/log.txt</file>
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <!-- 按天轮转，注：默认是使用UTC时间来轮转的，中国的时区要比它慢8小时，所以在中国时区的0点的时候并不会轮转，因为此时UTC时间为16:00，所以下面指定了上海时区 -->
                    <fileNamePattern>${logDir}/logs/log_%d{yyyy_MM_dd,Asia/Shanghai}.txt
                    </fileNamePattern>
                    <!-- 保存 30 天的历史记录(30天后会删除最老的日志文件)，最大大小为 600M -->
                    <maxHistory>${localMaxHistory}</maxHistory>
                    <totalSizeCap>${localSize}MB</totalSizeCap>
                </rollingPolicy>

                <encoder>
                    <!--
                    %d{HH:mm:ss}    时间：12:06:35
                    [%thread]       线程：[main]
                    %-5level        等级：INFO  （长度为5位，不够的补空格）
                    %msg            日志内容
                    %n              换行
                    -->
                    <pattern>${logFormat}</pattern>
                </encoder>
            </appender>

            <!--用于保存Bug的Appender配置-->
            <appender name="FILE_BUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                    <!-- 过虑掉小于ERROR级别的日志，所有级别: TRACE < DEBUG < INFO < WARN < ERROR -->
                    <level>ERROR</level>
                </filter>

                <file>${logDir}/bugs/bug.txt</file>
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <fileNamePattern>${logDir}/bugs/bug_%d{yyyy_MM_dd,Asia/Shanghai}.txt
                    </fileNamePattern>
                    <maxHistory>${localMaxHistory}</maxHistory>
                    <totalSizeCap>${localSize}MB</totalSizeCap>
                </rollingPolicy>

                <encoder>
                    <pattern>${logFormat}</pattern>
                </encoder>
            </appender>
            
            $pushServiceConfig

            <root level="trace">
                <appender-ref ref="FILE_LOG" />
                <appender-ref ref="FILE_BUG" />
                $rootPushServiceConfig
            </root>

        </configuration>

    """.trimIndent()
    }

    fun getGraylogSource(): String = graylogSource

    fun setGraylogSource(graylogSource: String) {
        this.graylogSource = graylogSource
    }

    //%d{yyyy_MM_dd HH:mm:ss} %-5level %logger{35}: %m%n%xEx
    //ch.qos.logback.classic.net.SyslogAppender

    //设置配置
    fun configureLogbackByString() {
        try {
            val lc = LoggerFactory.getILoggerFactory() as LoggerContext
            lc.stop()

            val config = JoranConfigurator()
            config.context = lc

            val stream = ByteArrayInputStream(getConfigStr().toByteArray())
            config.doConfigure(stream)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun setConfigure() {

    }

}